//
// Created by kriko on 2021/7/7.
//
// #include <unp.h>
#include <csapp.h>

void str_echo(int);
void sig_child(int);

int main(int argc, char* argv[]) {
    int listenfd, connfd;
    pid_t childpid;
    socklen_t clientLen;
    sockaddr_storage clientAddr;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <port>\n", argv[0]);
        return -1;
    }

    listenfd = Open_listenfd(atoi(argv[1]));
    Signal(SIGCHLD, sig_child);

    while (1) {
        clientLen = sizeof clientAddr;
        if ((connfd = accept(listenfd, (SA*)&clientAddr, &clientLen)) < 0) {
            if (errno == EINTR)
                continue;
            else
                unix_error("accept error");
        }

        if ((childpid = Fork()) == 0) {
            // child
            Close(listenfd);
            str_echo(connfd);
            return 0;
        }
        Close(connfd);
    }

    return 0;
}

void str_echo(int sockfd) {
    ssize_t n;
    char buf[MAXLINE];

    while((n = read(sockfd, buf, MAXLINE)) > 0) {
        Write(sockfd, buf, n);

        if (n < 0 && errno == EINTR) {
            continue;
        }else if (n < 0) {
            fprintf(stderr, "str_echo: read error");
        }
    }
}

void sig_child(int signo) {
    pid_t pid;
    int stat;

    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
        printf("child %d terminated\n", pid);
    }
    return;
}

